#pragma once

#ifndef EVENT_HANDLER
#define EVENT_HANDLER

#include "VirtualLocker.h"
#include "EventController.h"
#include "Utils.h"

namespace cevent {

class HandlerInterface {
public:
	virtual ~HandlerInterface() {};
private:
	friend class findEventByEvent;
	friend class EventController;
	template <typename C, typename S> friend class Handler;
	template <typename S> friend class HandlerDelStat;
	HandlerInterface(){};
	HandlerInterface(const HandlerInterface&); // undef
	void operator=(const HandlerInterface&); // undef
	virtual bool Call(const EventArgs* args) const = 0;
	virtual const void* GetSender() const = 0;
};

template <typename C, typename S>
class Handler : virtual private HandlerInterface{
public:
	typedef bool (C::*Delegate)(void* obj, const EventArgs* args);
	virtual const C* GetCaller() const {
		return caller;
	}
	bool Call(const EventArgs* args) const override{
		return (caller->*deleg)(sender, args);
	}
	const void* GetSender() const override{
		return sender;
	}
	virtual const Delegate GetDelegate() const {
		return deleg;
	}
private:
	friend class EventListener;
	friend class EventController;
	C* caller;
	S* sender;
	Delegate deleg;
	Handler(C* obj, Delegate del, S* sender) {
		this->caller = obj;
		this->deleg = del;
		this->sender = sender;
	}
};

template <typename S>
class HandlerDelStat : virtual private HandlerInterface{
public:
	typedef bool(*DelegateStatic)(void* obj, const EventArgs* args);
	bool Call(const EventArgs* args) const override{
		return (*deleg)(sender, args);
	}
	const void* GetSender() const override{
		return sender;
	}
	virtual const DelegateStatic GetDelegate() const {
		return deleg;
	}
private:
	friend class EventListener;
	friend class EventController;
	S* sender;
	DelegateStatic deleg;
	HandlerDelStat(DelegateStatic del, S* sender) {
		this->deleg = del;
		this->sender = sender;
	}
};

}

#endif // EVENT_HANDLER